package by.amakarevich.dataaccess.Impl;

import java.util.List;

import javax.persistence.TypedQuery;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaDelete;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Root;
import javax.persistence.metamodel.SingularAttribute;

import org.hibernate.jpa.criteria.OrderImpl;
import org.springframework.stereotype.Repository;

import by.amakarevich.dataaccess.BookingDao;
import by.amakarevich.datamodel.Booking;
import by.amakarevich.datamodel.Booking_;
import by.amakarevich.datamodel.UserAccount;

@Repository
public class BookingDaoImpl extends AbstractDaoImpl<Long, Booking> implements BookingDao  {
	protected BookingDaoImpl(){
		super(Booking.class);
	}
	@Override
	public List<Booking> getAllBookingByUser(UserAccount userAccount, boolean payStatus, boolean canceled){
        CriteriaBuilder cBuilder = getEm().getCriteriaBuilder();

        CriteriaQuery<Booking> criteria = cBuilder.createQuery(Booking.class);
        Root<Booking> root = criteria.from(Booking.class);

        criteria.select(root);
        root.fetch(Booking_.userAccount);
        criteria.distinct(true);
        criteria.where(cBuilder.and(cBuilder.equal(root.get(Booking_.userAccount), userAccount)),
        		cBuilder.and(cBuilder.equal(root.get(Booking_.payStatus), payStatus),cBuilder.equal(root.get(Booking_.canceled), canceled)));

        TypedQuery<Booking> query = getEm().createQuery(criteria);
        List<Booking> results = query.getResultList();
        return results;
	}
	
	@Override
    public List<Booking> getSortedAllBooking(SingularAttribute<Booking, ?> attr, boolean ascending, int startRecord, int pageSize) {
		CriteriaBuilder cBuilder = getEm().getCriteriaBuilder();

        CriteriaQuery<Booking> criteria = cBuilder.createQuery(Booking.class);
        Root<Booking> root = criteria.from(Booking.class);

        criteria.select(root);
        criteria.orderBy(new OrderImpl(root.get(attr), ascending));

        TypedQuery<Booking> query = getEm().createQuery(criteria);
        query.setFirstResult(startRecord);
        query.setMaxResults(pageSize);

        List<Booking> results = query.getResultList();
        return results;
    }
	

       
	@Override
    public void deleteBooking(Long id) {
        CriteriaBuilder cBuilder = getEm().getCriteriaBuilder();

        CriteriaDelete<Booking> root = cBuilder.createCriteriaDelete(Booking.class);
        Root<Booking> criteria = root.from(Booking.class);


        root.where(cBuilder.equal(criteria.get("id"), id));

        getEm().createQuery(root).executeUpdate();
	}
	
	@Override
	public Long getCount() {
		CriteriaBuilder cBuilder = getEm().getCriteriaBuilder();

		CriteriaQuery<Long> criteria = cBuilder.createQuery(Long.class);
		Root<Booking> root = criteria.from(Booking.class);

		criteria.select(cBuilder.count(root));

		TypedQuery<Long> query = getEm().createQuery(criteria);
		return query.getSingleResult();
	}
	
	@Override
	public Booking getByBookingId(Long bookingId) {
		CriteriaBuilder cBuilder = getEm().getCriteriaBuilder();
		CriteriaQuery<Booking> criteria = cBuilder
				.createQuery(Booking.class);
		Root<Booking> root = criteria.from(Booking.class);

		criteria.select(root);
		root.fetch(Booking_.userAccount);
		criteria.distinct(true);
		criteria.where(cBuilder.equal(root.get(Booking_.id),
				bookingId));

		TypedQuery<Booking> query = getEm().createQuery(criteria);
		Booking result = (Booking) query.getSingleResult();
		return result;
	}
	
}
